
#include <iostream>

#include "timerfd.hpp"
#include <unistd.h>
#include <poll.h>
#include <sys/timerfd.h>
#include <cstdint>        // 对于 uint64_t
#include <cerrno>         // 对于 errno
#include <cstring>        // 对于 strerror

TimerFd::TimerFd(int initSec, int peridoSec, TimerFdCallback&& cb):
_timerfd(createTimerFd()),
_isRunnning(false),
_initSec(initSec),
_peridoSec(peridoSec),
_cb(std::move(cb))
{

}
TimerFd::~TimerFd()
{
    close(_timerfd);
}
void TimerFd::start()
{
    struct pollfd pfd;
    pfd.fd = _timerfd;//监听该文件描述符
    pfd.events = POLLIN;
    _isRunnning = true;

    setTimerFd(_initSec, _peridoSec);
    while(_isRunnning){
        int nready = poll(&pfd, 1, 5000);
        if(-1 == nready && errno == EINTR)
        {
            continue;
        }
        else if(-1 == nready)
        {
            std::cerr<<"-1 == nready" << std::endl;
            return;
        }
        else if(0 == nready)
        {
            std::cout << "poll time_out" << std::endl;
        }
        else
        {
            if(pfd.revents & POLLIN)
            {
                handleRead();
                if(_cb)
                {
                    _cb();
                }
            }
        }
    }

}
void TimerFd::stop()
{
    if(_isRunnning)
    {
        _isRunnning = false;
        setTimerFd(0, 0);
    }
}
int TimerFd::createTimerFd()
{
    int fd = timerfd_create(CLOCK_MONOTONIC, 0);
    if(fd < 0)
    {
        perror("createTimerFd");
        return -1;
    }
    return fd;
}
void TimerFd::handleRead()
{
    uint64_t one = 1;
    ssize_t ret = read(_timerfd, &one, sizeof(uint64_t));
    if(ret != sizeof(uint64_t))
    {
        perror("handleRead");
    }
}
void TimerFd::setTimerFd(int initSec, int peridoSec)
{
    struct itimerspec newtime;
    newtime.it_value.tv_sec = initSec;//起始时间，秒
    newtime.it_value.tv_nsec = 0;//起始时间，纳秒

    newtime.it_interval.tv_sec = peridoSec;//周期
    newtime.it_interval.tv_nsec = 0;                                           
    
    int ret = timerfd_settime(_timerfd, 0, &newtime, nullptr);
    if(ret < 0)
    {
        perror("setTimerFd");
        return;
    }
}



